# -*- coding: utf-8 -*-
"""
Created on Tue Dec 18 15:20:03 2018

@author: 刘丹

该类用于生成基础模拟数据和实时模拟数据
仅需定时插入数据到数据库即可，不需要对外提供服务
"""
import pandas as pd
import numpy as np
import random
import datetime
from pao import log
from pao.data import process_db
from gov.data_process.data import DataProcess


class Gener_Sim_Data(DataProcess):
    
    equip_type=['ax','ay','az','bx','by','bz','cx','cy','cz']
    
    def __init__(self,db_addr,db_port,date):
        DataProcess.__init__(self,db_addr,db_port)
        self.date=date


    def next_hour_date(self):
        #生成当前日期的下一小时整点的日期值
        dates=pd.date_range(self.date.strftime("%Y-%m-%d"),periods=25,freq='H')
        insert_hour=self.date.hour+1
        next_hour_date=dates[insert_hour]
        return next_hour_date

    def basic_data_get(self):
        #从数据库读取dlh_num和dlh_type
        dlh_data=''
        def process_func(db):
            nonlocal dlh_data
            collection_dlh = db['dlh_type']
            cur=collection_dlh.find({})
            dlh_data=list(cur[:])
        process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)
        dlh_df=pd.DataFrame(dlh_data)
        return dlh_df

    def insert_ydb(self,cal_A):
        #循环计算电流值并插入ydb中
        insertdate=self.next_hour_date()
        dlh_df=self.basic_data_get()
        log('ydb数据插入','插入数据时间为：%s' % (insertdate))
        def process_func(db):
            for i in range(len(dlh_df)):
                if (i+1) % 2000 == 0:
                    log('ydb生成数据情况','已完成%s个用户数据插入' %(i+1))
                dlhnum=dlh_df.dlh_num.iloc[i]
                dlhtype=dlh_df.dlh_type.iloc[i]
                cal_A_tep=cal_A[self.equip_type][cal_A.dlh_num==dlhnum]
                cal_A_single=np.array(cal_A_tep)
                ydb_day=self.use_time(dlhtype)
                dldata=np.sum(np.array(ydb_day*cal_A_single))
                dlhnum=int(dlhnum)
                insert_data1={'date':insertdate
                        ,'dlh_num':dlhnum
                        ,'datalist':dldata
                        ,'power':dldata*220
                        ,'seq_num':random.randint(1000000000,10000000000)}
                collection_ydb=db['ydb']
                collection_ydb.insert(insert_data1)           
        process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)
        
    def insert_TJ_ydb(self):
        #向TJ_ydb中插入数据，插入的数据时间为date日期的前一天的用电量
        date=self.date+ datetime.timedelta(days = -1)
        dates=pd.date_range(date.strftime("%Y-%m-%d"),periods=25,freq='H')
        ydb_list=''
        log('TJ_ydb数据插入','插入数据时间为：%s' % (dates[0]))
        def process_func(db):
            nonlocal ydb_list
            collection_ydb=db['ydb']
            cur_ydb=collection_ydb.find({'date': {'$gte': dates[0], '$lt': dates[-1]}})
            ydb_list=list(cur_ydb[:])
        process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)
        ydb_df=pd.DataFrame(ydb_list)
        ydl=sum(ydb_df['datalist'].tolist())
        def process_func(db):
            insert_data={'ydl':ydl,'date':dates[0],'ds':ydl*0.22}
            collection_tj_ydb=db['TJ_ydb']
            collection_tj_ydb.insert_one(insert_data)
        process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)

    def insert_analy_equip(self,cal_A,dlh_equip_num):
        #循环计算各电流环各电器的电流值并插入analy_equip中
        insertdate=self.next_hour_date()
        dlh_df=self.basic_data_get()
        log('analy_equip数据插入','插入数据时间为：%s' % (insertdate))
        for i in range(len(dlh_df)):
            if (i+1) % 2000 == 0:
                log('analy_equip生成数据情况','已完成%s个用户数据插入' %(i+1))
            dlhnum=dlh_df.dlh_num.iloc[i]
            dlhtype=dlh_df.dlh_type.iloc[i]
            cal_A_tep=cal_A[self.equip_type][cal_A.dlh_num==dlhnum]
            cal_A_single=np.array(cal_A_tep)
            ydb_day=self.use_time(dlhtype)
            step1_data=ydb_day*cal_A_single
            step2_data=pd.DataFrame(columns=['dlh_num','date','equip_type','meanA'])
            for i in range(len(self.equip_type)):
                #dlhnum_list=[dlhnum for x in range(24)]
                equipname=self.equip_type[i]
                tep_df=pd.DataFrame({'dlh_num':dlhnum,'date':insertdate,'equip_type':equipname
                                     ,'meanA':step1_data[self.equip_type[i]].tolist()})
                step2_data=step2_data.append(tep_df,ignore_index=True)
            step2_data=step2_data[~step2_data['meanA'].isin([0])]
            #将电器种类拆分成具体的电器名字，依据每个用户所拥有的电器名字随机拆分
            step3_data=pd.DataFrame(columns=['dlh_num','date','equip_type','meanA','equip_name'])
            test=dlh_equip_num[dlh_equip_num.dlh_num==dlhnum]
            for i in range(len(step2_data)):
                tep_b=step2_data.equip_type.iloc[i]
                tep_a=test[test.equip==tep_b].equip_name.iloc[0]
                rand=[random.random() for x in range(len(tep_a))]
                rand=np.array(rand)/sum(rand)
                rand=rand*step2_data.meanA.iloc[i]
                tep_addf=pd.DataFrame({'dlh_num':[dlhnum for x in range(len(tep_a))]
                ,'date':[insertdate for x in range(len(tep_a))]
                ,'equip_type':[tep_b for x in range(len(tep_a))]
                ,'meanA':rand.tolist(),'equip_name':tep_a})
                step3_data=step3_data.append(tep_addf,ignore_index=True)
            #插入数据    
            def process_func(db):
                collection_ydb=db['analy_equip']
                for i in range(len(step3_data)):
                    insert_data={'date':step3_data['date'].iloc[i]
                                ,'dlh_num':step3_data['dlh_num'].iloc[i]
                                ,'meanA':step3_data['meanA'].iloc[i]
                                ,'equip_type':step3_data['equip_type'].iloc[i]
                                ,'equip_name':step3_data['equip_name'].iloc[i]}
                    collection_ydb.insert(insert_data)           
            process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)

    def insert_yichangdata(self):
        yctype=['超出电流额定量','电流环失去通讯异常']
        dlh_df=self.basic_data_get()
        dlhnum=dlh_df.dlh_num.tolist()
        rand=random.randint(1,3)
        yc_dlh=random.sample(dlhnum,rand)
        yc_yy=[random.sample(yctype,1)[0] for x in range(rand)]
        yichang_date=datetime.datetime.now()
        log('ycdatatable数据插入','插入数据时间当前时间' )
        def process_func(db):
            collection_yctable=db['ycdatatable']
            for i in range(len(yc_dlh)):
                insert_data={'date':yichang_date,'dlh_num':yc_dlh[i],'yc_type':yc_yy[i]}
                collection_yctable.insert(insert_data)
        process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)
        
    def cal_data_2mins(self):
        #计算每两分钟一次的实时数据每小时的值
        t_H=self.date.hour
        cxdate=pd.date_range(self.date.strftime("%Y-%m-%d"),periods=25,freq='H')[t_H]
        #查询数据
        read_list=''
        def process_func(db):
            nonlocal read_list
            collection1=db['ydb']
            cur=collection1.find({'date':cxdate})
            read_list=list(cur[:])
        process_db(self.db_addr, self.db_port, 'GovNetThing', process_func)
        read_data=pd.DataFrame(read_list)
        inser_list_zong=[]
        for i in range(len(read_data)):
            tep1=[1 for x in range(30)]
            tep2=[0.5*random.random() for x in range(30)]
            tep3=np.array(tep1)+np.array(tep2)
            tep4=tep3/sum(tep3)
            dlhnum=read_data.dlh_num.iloc[i]
            data_sum=read_data.datalist.iloc[i]
            inser_A=tep4*data_sum
            dates=pd.date_range(cxdate,periods=30,freq='120s')
            for j in range(30):
                ins_dict={'dlh_num':dlhnum,'mean_A':inser_A[j],'date':dates[j],'minutes':j*2}
                inser_list_zong.append(ins_dict)
        self.inser_df_zong=pd.DataFrame(inser_list_zong)
        return self.inser_df_zong
    
    def insert_data_2mins(self):
        #每两分钟插入一次实时数据的代码
        insert_time=datetime.datetime.now()
        mins=insert_time.minute
        if mins==0:
            self.inser_df_zong=self.cal_data_2mins()        
        ins_data=self.inser_df_zong[self.inser_df_zong['minutes']==mins]
        log('shishidata_every_2mins数据插入','插入数据时间当前时间')
        def process_func(db):
            collection_every2mins=db['shishidata_every_2mins']
            for i in range(len(ins_data)):
                insert_data={'dlh_num':int(ins_data.dlh_num.iloc[i]),
                             'date':insert_time,
                             'mean_A':ins_data.mean_A.iloc[i]
                        }
                collection_every2mins.insert_one(insert_data)
        process_db(self.db_addr,self.db_port,'GovNetThing',process_func)

    def use_time(self,dlhtype):
        #该函数用于生成该小时中9种类型电器的使用时长
        #对于单用户
        #生成的是date日期的下一个小时的数据
        WORK_HIGH3=[0,0,0,0,0,0,1,1,1,1,0,1,1,1,0,0,0,1,1,1,1,1,0,0]
        NIGHT_WEEK=[1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
        NIGHT_WORK=[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1]
        DAY_WORK=[0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0]
        ydb_day=pd.DataFrame(columns=self.equip_type)
        
        tep_hour=self.date.hour
        if tep_hour==23:
            hour_of_day=0
        else:
             hour_of_day=tep_hour+1 
    
        if dlhtype=='high3':
            #生成ax,ay,bx列
            rand=random.random()
            if rand>0.9:
                ydb_day.ax=[0]
                ydb_day.ay=[0]
                ydb_day.bx=[0]
            else:
                ydb_day.ax=[WORK_HIGH3[hour_of_day]*random.random()]
                ydb_day.bx=[WORK_HIGH3[hour_of_day]*random.random()]
                ydb_day.ay=[WORK_HIGH3[hour_of_day]*0.5+0.5*random.random()]
            #生成cx,cy列
            rand=random.random()
            if rand>0.7:
                ydb_day.cx=[0]
                ydb_day.cy=[0]
            else:
                ydb_day.cx=[WORK_HIGH3[hour_of_day]*random.random()]
                ydb_day.cy=[WORK_HIGH3[hour_of_day]*0.5+0.5*random.random()]
            #生成by列，考虑季节
            rand=random.random()
            if (self.date.month in [4,5,6,7,8,9,10]) and (rand<0.95):
                ydb_day.by=[WORK_HIGH3[hour_of_day]*0.5+0.5*random.random()]
            elif (self.date.month in [1,2,3,11,12]) and rand<0.7:
                ydb_day.by=[WORK_HIGH3[hour_of_day]*0.5+0.5*random.random()]
            else:
                ydb_day.by=[0]
            #生成az,bz 列
            rand=random.random()
            if rand<0.95:
                ydb_day.az=[1]
                ydb_day.bz=[1]
            else:
                ydb_day.az=[0]
                ydb_day.bz=[0]
            ydb_day.cz=[0]
        if dlhtype=='night':
            if self.date.isoweekday() in [6,7]:
                rand=random.random()
                if rand<0.8:
                    ydb_day.ax=[NIGHT_WEEK[hour_of_day]*random.random()]
                else:
                    ydb_day.ax=[0]
                rand=random.random()
                if rand<0.95:
                    ydb_day.ay=[NIGHT_WEEK[hour_of_day]*0.5+0.5*random.random()]
                else:
                    ydb_day.ay=[0]
                rand=random.random()
                if rand<0.98:
                    ydb_day.az=[1]
                else:
                    ydb_day.az=[0]
                rand=random.random()
                if rand<0.7:
                    ydb_day.bx=[NIGHT_WEEK[hour_of_day]*random.random()]
                    ydb_day.bz=[1]
                else:
                    ydb_day.bx=[0]
                    ydb_day.bz=[0]
                rand=random.random()
                if (self.date.month in [4,5,6,7,8,9,10]) and (rand<0.9):
                    ydb_day.by=[NIGHT_WEEK[hour_of_day]*0.5+0.5*random.random()]
                elif (self.date.month in [1,2,3,11,12]) and rand<0.2:
                    ydb_day.by=[NIGHT_WEEK[hour_of_day]*0.5+0.5*random.random()]
                else:
                    ydb_day.by=[0]
            if self.date.isoweekday() in [1,2,3,4,5]:
                rand=random.random()
                if rand<0.5:
                    ydb_day.ax=[NIGHT_WORK[hour_of_day]*random.random()]
                else:
                    ydb_day.ax=[0]
                rand=random.random()
                if rand<0.9:
                    ydb_day.ay=[NIGHT_WORK[hour_of_day]*0.5+0.5*random.random()]
                else:
                    ydb_day.ay=[0]
                rand=random.random()
                if rand<0.98:
                    ydb_day.az=[1]
                else:
                    ydb_day.az=[0]
                rand=random.random()
                if rand<0.3:
                    ydb_day.bx=[NIGHT_WORK[hour_of_day]*random.random()]
                else:
                    ydb_day.bx=[0]
                rand=random.random()
                if rand<0.7:    
                    ydb_day.bz=[1]
                else:
                    ydb_day.bz=[0]
                rand=random.random()
                if (self.date.month in [4,5,6,7,8,9,10]) and (rand<0.9):
                    ydb_day.by=[NIGHT_WORK[hour_of_day]*0.5+0.5*random.random()]
                elif (self.date.month in [1,2,3,11,12]) and rand<0.2:
                    ydb_day.by=[NIGHT_WORK[hour_of_day]*0.5+0.5*random.random()]
                else:
                    ydb_day.by=[0]
            ydb_day.cx=[0]
            ydb_day.cy=[0]
            ydb_day.cz=[0]
        if dlhtype=='day':
            if self.date.isoweekday() in [6,7]:
                rand=random.random()
                if rand<0.2:
                    ydb_day.ax=[DAY_WORK[hour_of_day]*random.random()]
                    ydb_day.ay=[DAY_WORK[hour_of_day]*0.5+0.5*random.random()]
                    ydb_day.bx=[DAY_WORK[hour_of_day]*random.random()]
                    ydb_day.cx=[DAY_WORK[hour_of_day]*random.random()]
                    ydb_day.cy=[DAY_WORK[hour_of_day]*0.5+0.5*random.random()]
                else:
                    ydb_day.ax=[0]
                    ydb_day.ay=[0]
                    ydb_day.bx=[0]
                    ydb_day.cx=[0]
                    ydb_day.cy=[0]
                rand2=random.random()
                if (self.date.month in [4,5,6,7,8,9,10]) and (rand<0.2) and rand2<0.95:
                    ydb_day.by=[DAY_WORK[hour_of_day]*0.5+0.5*random.random()]
                elif (self.date.month in [4,5,6,7,8,9,10]) and (rand<0.2) and rand2<0.6:
                    ydb_day.by=[DAY_WORK[hour_of_day]*0.5+0.5*random.random()]
                else:
                    ydb_day.by=[0]
            if self.date.isoweekday() in [1,2,3,4,5]:
                ydb_day.ax=[DAY_WORK[hour_of_day]*random.random()]
                ydb_day.ay=[DAY_WORK[hour_of_day]*0.5+0.5*random.random()]
                ydb_day.bx=[DAY_WORK[hour_of_day]*random.random()]
                ydb_day.cx=[DAY_WORK[hour_of_day]*random.random()]
                ydb_day.cy=[DAY_WORK[hour_of_day]*0.5+0.5*random.random()]
                rand=random.random()
                if (self.date.month in [4,5,6,7,8,9,10]) and (rand<0.95):
                    ydb_day.by=[DAY_WORK[hour_of_day]*0.5+0.5*random.random()]
                elif (self.date.month in [4,5,6,7,8,9,10]) and rand2<0.6:
                    ydb_day.by=[DAY_WORK[hour_of_day]*0.5+0.5*random.random()]
                else:
                    ydb_day.by=[0]
            rand=random.random()
            if rand<0.98:
                ydb_day.az=[1]
            else:
                ydb_day.az=[0]
            rand=random.random()
            if rand<0.95:
                ydb_day.bz=[1]
            else:
                ydb_day.bz=[0]
            rand=random.random()
            if rand<0.8:
                ydb_day.cz=[1]
            else:
                ydb_day.cz=[0]
        return ydb_day


